﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIA.Foundation;
using VIA.Integration.Automatics;
using VIA.Integration.Domain;
using VIA.Integration;
using VIA.Presentation;
using VIA.SiMoJi.Domain;
using System.Collections.ObjectModel;

namespace VIA.SiMoJi.Presentation
{
    [Editor(typeof(IFoxconnMES))]
    public interface IFoxconnMESView : IWindow, IObjectEditor
    {

    }

    [ViewModel(typeof(IFoxconnMESView))]
    internal class FoxconnMESViewModel : ViewModel<IFoxconnMESView>, IObjectEditor
    {
        #region Services
        readonly IServiceProvider _service;
        readonly ILogger _logger;
        readonly ICommandFactory _commandFactory;
        readonly IMessageService _messageService;
        readonly ICurrentRecipe _currentRecipe;
        readonly IDispatcherService _dispatcherService;
        readonly IApplicationLog _applicationLog;
        #endregion

        #region Fields
        string _messageToken;
        string _title;
        FoxconnMESOption _option;
        IFoxconnMES _foxconnMES;
        #endregion

        #region Properties
        public string Title
        {
            get => _title;
            set => SetProperty(ref _title, value);
        }

        public FoxconnMESOption Option
        {
            get => _option;
            set => SetProperty(ref _option, value);
        }

        public IFoxconnMES FoxconnMES
        {
            get => _foxconnMES;
            set
            {
                if (SetProperty(ref _foxconnMES, value))
                {
                    if (_foxconnMES != null)
                    {
                        if (!string.IsNullOrEmpty(_foxconnMES.Name))
                            Title = _foxconnMES.Name;
                        if (_foxconnMES is IHasOption<FoxconnMESOption>)
                        {
                            Option = _currentRecipe.Get<FoxconnMESOption>(_foxconnMES.Id);
                        }
                        _foxconnMES.IsConnectedChanged -= Client_IsConnectedChanged;
                        _foxconnMES.IsConnectedChanged += Client_IsConnectedChanged;
                    }
                }
            }
        }

        public IObject EditObject
        {
            get => FoxconnMES;
            set
            {
                if (value is IFoxconnMES foxconnMES)
                {
                    FoxconnMES = foxconnMES;
                }
                else
                    throw new InvalidOperationException($"编辑的对象类型必须是{typeof(IFoxconnMES)}");
            }
        }

        public bool IsConnected => _foxconnMES != null ? _foxconnMES.IsConnected : false;

        public ObservableCollection<LogItem> LogItems { get; }
        private string _testBarcode1 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        private string _testBarcode2 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        private string _testBarcode3 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        private string _testBarcode4 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        private string _testBarcode5 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        private string _testBarcode6 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        private string _testBarcode7 = DateTime.Now.ToString("yyyyMMddHHmmssss");
        public string TestBarcode1
        {
            get => _testBarcode1;
            set => SetProperty(ref _testBarcode1, value);
        }
        public string TestBarcode2
        {
            get => _testBarcode2;
            set => SetProperty(ref _testBarcode2, value);
        }
        public string TestBarcode3
        {
            get => _testBarcode3;
            set => SetProperty(ref _testBarcode3, value);
        }
        public string TestBarcode4
        {
            get => _testBarcode4;
            set => SetProperty(ref _testBarcode4, value);
        }
        public string TestBarcode5
        {
            get => _testBarcode5;
            set => SetProperty(ref _testBarcode5, value);
        }
        public string TestBarcode6
        {
            get => _testBarcode6;
            set => SetProperty(ref _testBarcode6, value);
        }
        public string TestBarcode7
        {
            get => _testBarcode7;
            set => SetProperty(ref _testBarcode7, value);
        }
        #endregion

        #region Commands
        public IRelayCommand ConnectCommand { get; }
        public IRelayCommand DisConnectCommand { get; }
        public IRelayCommand SaveOptionCommand { get; }
        public IRelayCommand StackInCommand { get; }
        public IRelayCommand StackOutCommand { get; }
        public IRelayCommand StackLQCommand { get; }
        #endregion

        #region Constructor
        public FoxconnMESViewModel(IServiceProvider service)
        {
            _service = service;
            _logger = service.GetService<ILoggerFactory>().CreateLogger("MES");
            _commandFactory = service.GetService<ICommandFactory>();
            _messageService = service.GetService<IMessageService>();
            _currentRecipe = service.GetService<ICurrentRecipe>();
            _applicationLog = service.GetService<IApplicationLog>();
            _applicationLog.SetMaxLength(_messageToken, 150);
            _messageToken = Guid.NewGuid().ToString();
            _dispatcherService = service.GetService<IDispatcherService>();
            LogItems = _applicationLog.Get(_messageToken);
            ConnectCommand = _commandFactory.Create(Connect);
            StackInCommand = _commandFactory.Create(StackIn);
            StackOutCommand = _commandFactory.Create(StackOut);
            StackLQCommand = _commandFactory.Create(StackLQ);
            DisConnectCommand = _commandFactory.Create(DisConnect, () => IsConnected);
            SaveOptionCommand = _commandFactory.Create(SaveOption);
        }
        #endregion

        #region CommandHandles
        void Connect()
        {
            try
            {
                _foxconnMES.Connect();
                if (IsConnected)
                {
                    LogInfo($"MES连接成功.");
                }
                else
                {
                    LogError($"MES连接失败");
                }
            }
            catch (Exception ex)
            {
                _messageService.ShowError(View, $"连接失败{ex.Message}");
            }
        }

        void DisConnect()
        {
            try
            {
                _foxconnMES.Disconnect();
                LogInfo($"MES断开连接成功.");
            }
            catch (Exception ex)
            {
                _messageService.ShowError(View, $"断开失败{ex.Message}");
            }
        }

        async void SaveOption()
        {
            try
            {
                _currentRecipe.Set(_foxconnMES.Id, Option);
                await _currentRecipe.SaveAsync();
                if (_foxconnMES is IHasOption<FoxconnMESOption> o)
                    o.Option = Option;
                _messageService.ShowMessage(View, $"参数保存成功");
            }
            catch (Exception ex)
            {
                _messageService.ShowError(View, $"参数保存异常.{ex.Message}");
            }
        }

        async Task StackIn()
        {
            var recordStack = await _foxconnMES.StackIn(new string[] { _testBarcode1, _testBarcode2, _testBarcode3, _testBarcode4, _testBarcode5, _testBarcode6, _testBarcode7 });
            LogWarning($"{recordStack.ReturnString}");
        }

        async void StackOut()
        {
            var recordStack = await _foxconnMES.StackOut(new string[] { _testBarcode1, _testBarcode2, _testBarcode3, _testBarcode4, _testBarcode5, _testBarcode6, _testBarcode7 });
            LogWarning($"{recordStack.ReturnString}");
        }

        async Task StackLQ()
        {
            var recordStack = await _foxconnMES.StackLQ(new string[] { _testBarcode1, _testBarcode2, _testBarcode3, _testBarcode4, _testBarcode5, _testBarcode6, _testBarcode7 });
            LogWarning($"{recordStack.ReturnString}");
        }
        #endregion

        #region Functions
        void Client_IsConnectedChanged(IDevice device)
        {
            _dispatcherService.InvokeAsync(() =>
            {
                _commandFactory.RaiseCanExecuteChanged();
                RaisePropertyChanged(nameof(IsConnected));
            });
        }

        #endregion

        #region  Log 打印
        protected void LogInfo(string message)
        {
            _logger.LogInformation(message);
            _applicationLog.Log(_messageToken, message);
        }

        protected void LogWarning(string message)
        {
            _logger.LogWarning(message);
            _applicationLog.LogWarning(_messageToken, message);
        }

        protected void LogError(string message)
        {
            _logger.LogError(message);
            _applicationLog.LogError(_messageToken, message);
        }

        protected void LogError(Exception e, string message)
        {
            _logger.LogError(e, message);
            _applicationLog.LogError(_messageToken, message);
        }
        #endregion
    }
}
